#include "GameStateMachine.h"
#include <cstddef> // get the definition of NULL and size_t
#include "GameState.h"

lj::GameStateMachine::GameStateMachine()
	: m_CurrentGameState(NULL)
{

}

lj::GameStateMachine::~GameStateMachine()
{

}

void lj::GameStateMachine::AddGameState(lj::GameState* gameState)
{
	m_RegisteredGameStates.push_back(gameState);
}

void lj::GameStateMachine::QueueGameState(lj::EGameState gameState)
{
	m_QueuedStates.push_back(gameState);
}
	
void lj::GameStateMachine::SwitchToGameState(lj::EGameState gameState)
{
	while(!m_QueuedStates.empty())
	{
		m_QueuedStates.pop_front();
	}

	m_QueuedStates.push_back(gameState);
}

void lj::GameStateMachine::ActivateState(lj::EGameState toState)
{
	const size_t size = m_RegisteredGameStates.size();
	for(size_t i = 0; i < size; ++i)
	{
		if(m_RegisteredGameStates[i]->GetID() == toState)
		{
			m_CurrentGameState = m_RegisteredGameStates[i];
			break;
		}
	}

	if(m_CurrentGameState != NULL)
	{
		m_CurrentGameState->Init();
	}
}

void lj::GameStateMachine::Update()
{
	if(m_CurrentGameState && m_CurrentGameState->IsFinished() && !m_QueuedStates.empty())
	{
		m_CurrentGameState->Exit();
		m_CurrentGameState = GetGameStateById(m_QueuedStates.front());
		m_QueuedStates.pop_front();
		m_CurrentGameState->Init();
	}
	else if(!m_CurrentGameState && !m_QueuedStates.empty())
	{
		m_CurrentGameState = GetGameStateById(m_QueuedStates.front());
		m_QueuedStates.pop_front();
		m_CurrentGameState->Init();
	}

	if(m_CurrentGameState)
	{
		m_CurrentGameState->Update();
	}
}

lj::GameState* lj::GameStateMachine::GetGameStateById(lj::EGameState gameStateId)
{
	const size_t size = m_RegisteredGameStates.size();
	for(size_t i = 0; i < size; ++i)
	{
		if(m_RegisteredGameStates[i]->GetID() == gameStateId)
		{
			return m_RegisteredGameStates[i];
		}
	}

	return NULL;
}
